package cn.elegent.tx.core.storage.impl;

import cn.elegent.tx.data.ElegentData;
import cn.elegent.tx.config.RollBackConfig;
import cn.elegent.tx.context.ElegentACTXContext;
import cn.elegent.tx.core.entity.TransactionEntity;
import cn.elegent.tx.core.entity.state.TransactionState;
import cn.elegent.tx.core.rollback.RollBackDTO;
import cn.elegent.tx.core.storage.TransactionStorage;
import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * TransactionManager
 * @description  事务管理器的实现类
 * @author WGL
 * @date 2022/11/7 0:29
*/
@Component
public class TransactionStorageImpl implements TransactionStorage {


    @Autowired
    private ElegentData elegentData;
    /**
     * 事务初始化
     * @param transactionEntity
     * @return
     */
    @Override
    public boolean begin(TransactionEntity transactionEntity) {
        /**
         * 如果AC框架提供的 全局ID为空--执行主事务初始化的逻辑
         */
        elegentData.hset(transactionEntity.getMainName()+":"+transactionEntity.getTransactionId()+":"+"state", transactionEntity.getChildName(), TransactionState.BEGIN.getState());

        elegentData.hset(transactionEntity.getMainName()+":"+transactionEntity.getTransactionId()+":"+"server", transactionEntity.getChildName(), RollBackConfig.getServerName());

        return true;

    }

    /**
     * 修改事务状态
     * @param transactionEntity
     * @param transactionState
     * @return
     */
    @Override
    public boolean change(TransactionEntity transactionEntity,TransactionState transactionState) {
        elegentData.hset(transactionEntity.getMainName()+":"+transactionEntity.getTransactionId()+":"+"state", transactionEntity.getChildName(), transactionState.getState());
        return true;
    }

    /**
     * 事务销毁
     * @return
     */
    @Override
    public boolean destroy(TransactionEntity transactionEntity) {
        elegentData.hdel(transactionEntity.getTransactionId(),transactionEntity.getChildName());
        return true;
    }


    /**
     * 获取所有需要回回滚的信息
     * @param transactionEntity
     */
    @Override
    public List<RollBackDTO> getAllNeedRollBackInfo(TransactionEntity transactionEntity,TransactionState state) {

        List<RollBackDTO> result = new ArrayList<RollBackDTO>();
        String transactionId = transactionEntity.getTransactionId();
        String mainName = transactionEntity.getMainName();
        //从redis中的状态一栏数据中找到当前事务中属于成功执行的事务
        Map<String, String> hmget = elegentData.hgetAll(mainName + ":" + transactionId + ":state");
        for(Object key : hmget.keySet()){
            if(state.getState().equals(hmget.get(key))){
                RollBackDTO rollBackDTO = new RollBackDTO();
                rollBackDTO.setChildName(key.toString());
                rollBackDTO.setMainName(mainName);
                rollBackDTO.setServerName(elegentData.hget(mainName+":"+transactionId+":server",key.toString()).toString());
                rollBackDTO.setTransactionId(transactionId);
                rollBackDTO.setArgs(elegentData.hget(mainName+":"+transactionId+":args",key.toString()).toString());
                result.add(rollBackDTO);
            }
        }
        return result;
    }

    /**
     * 保存回滚参数
     * @param transactionEntity
     */
    @Override
    public boolean saveRollBackArgs(TransactionEntity transactionEntity) {
        Map<String, Object> args = ElegentACTXContext.getSnapshot().getData();
        if(args==null){
            args = new HashMap<String,Object>();
        }
        elegentData.hset(transactionEntity.getMainName()+":"+transactionEntity.getTransactionId()+":"+"args", transactionEntity.getChildName(), JSON.toJSONString(args));
        return true;
    }
}